#include "../inc/skyXMLParser.h"
//#include "../inc/xPool.h"
namespace Sky
{
	namespace NXMLParser
	{

#define TYPE_XML_ELEMENT		1
#define TYPE_XML_ELEMENT_END	2
#define TYPE_XML_ELEMENT_SELF	3

		TVoid xElement::addAttribute( xIDMap* att )
		{
			xAttribute* attr = new xAttribute();
			attr->pNext = vNull;
			attr->val = vNull;
			attr->att = att;
			if(pAttr == vNull)
			{
				pAttr = attr;
				pLast = attr;
			}
			else
			{
				pLast->pNext = attr;
				pLast = attr;
			}
		}

		TVoid xElement::delAttribute()
		{
			xAttribute* pFirst = pAttr;
			while(pFirst)
			{
				pAttr = pAttr->pNext;
				delete pFirst;
				pFirst = pAttr;
			}
		}

		TVoid xElement::setAttributeValue( TChar* val )
		{
			pLast->val = val;
		}
		TVoid NXMLParser::xXMLTinyParser::Begin()
		{
			mState = STATE_XML_XML;
		}
		TBool xXMLTinyParser::Parse( xDomBuilder* domMaker, TChar* pData, TInt nSize )
		{
			int i = 0;
			TChar* pBegin = pData;
			TChar* pEnd = vNull;
			TInt   jumped = 0;;
			TBool found;
			TInt depth = 0;
			domMaker->BeginDocument();
			while(i < nSize)
			{
				switch(mState)
				{
				case STATE_XML_XML:
					mState = STATE_XML_ELEMENT_BEGIN;
					break;
				case STATE_XML_ELEMENT_BEGIN:
					mState = STATE_XML_ELEMENT_NAME;
					break;
				case STATE_XML_ELEMENT_NAME:
					{
						pBegin = &pData[i];
						jumped = 0;
						found = findElementName(&pBegin,&pEnd,&jumped,nSize - i);
						if(found)
						{
							depth ++;
							mState = STATE_XML_ATTRIBUTE_NAME;
							domMaker->ElementName(pBegin,pEnd - pBegin);
							pBegin = pEnd;
							i += jumped;
						}
						else
						{
							mState = STATE_XML_ELEMENT_FINISH;
						}
						break;
					}
				case STATE_XML_ATTRIBUTE_NAME:
					{
						pBegin = &pData[i];
						jumped = 0;
						found = findAttributeName(&pBegin,&pEnd,&jumped,nSize - i);
						if(found)
						{
							mState = STATE_XML_ATTRIBUTE_VALUE;
							domMaker->AttributeName(pBegin,pEnd - pBegin);
							pBegin = pEnd;
						}
						else
						{
							mState = STATE_XML_ELEMENT_VALUE;
						}
						i += jumped;
					}
					break;
				case STATE_XML_ATTRIBUTE_VALUE:
					{
						pBegin = &pData[i];
						jumped = 0;
						found = findAttributeValue(&pBegin,&pEnd,&jumped,nSize - i);
						if(found)
						{
							mState = STATE_XML_ATTRIBUTE_NAME;
							domMaker->AttributeValue(pBegin,pEnd - pBegin);
							pBegin = pEnd;
						}
						else
						{
							mState = STATE_XML_ATTRIBUTE_NAME;
						}
						i += jumped;
					}
					break;
				case STATE_XML_ELEMENT_VALUE:
					{
						pBegin = &pData[i];
						jumped = 0;
						found = findElementValue(&pBegin,&pEnd,&jumped,nSize - i);
						if(found)
						{
							
							mState = STATE_XML_ELEMENT_FINISH;
							domMaker->ElementValue(pBegin,pEnd - pBegin);
							pBegin = pEnd;
						}
						else
						{
							mState = STATE_XML_ELEMENT_NAME ;
						}
						i += jumped;
					}
					break;
				case STATE_XML_ELEMENT_FINISH:
					{
						pBegin = &pData[i];
						jumped = 0;
						found = findElementFinish(&pBegin,&pEnd,&jumped,nSize - i);
						if(found)
						{
							domMaker->EndElement();
							depth--;
							if(depth == 0)
							{
								mState = STATE_XML_XML_FINISH;
							}
							else
							{
								mState = STATE_XML_ELEMENT_NAME;
								pBegin = pEnd;
							}
							
						}
						else
						{
							mState = STATE_XML_ELEMENT_FINISH;
						}
						i += jumped;
					}
					break;
				case STATE_XML_XML_FINISH:
					i = nSize;
					break;
				}
			}
			domMaker->EndDocument();
			return vTrue;
		}

		TBool xXMLTinyParser::findElementName( TChar** pBegin,TChar** pEnd,TInt* len ,TInt left)
		{
			TChar* pCur = *pBegin;
			TChar* pIndex = pCur;
			TInt   curLen = 0;
			TBool  bStarted = vFalse;
			for(;;)
			{
				if( (*pIndex >= _XT('A') && *pIndex <= _XT('Z')) ||
					(*pIndex >= _XT('a') && *pIndex <= _XT('z')) ||
					(*pIndex >= _XT('0') && *pIndex <= _XT('9')))
				{
					
					if(bStarted == vFalse)
					{
						bStarted = vTrue;
						*pBegin = pIndex;
					}
				}
				else
				{
					if(bStarted)
					{
						break;
					}
					if(*pIndex == _XT('/'))
					{
						*len = 0;
						return vFalse;
					}
				}
				pIndex++;
				curLen ++;
			}
			if(bStarted == vTrue)
			{
				*pEnd = pIndex;
				*len = curLen;
				return vTrue;
			}
			return vFalse;
		}

		TBool xXMLTinyParser::findAttributeName( TChar** pBegin,TChar** pEnd,TInt* len ,TInt left)
		{
			TChar* pCur = *pBegin;
			TChar* pIndex = pCur;
			TInt   curLen = 0;
			TBool  bStarted = vFalse;
			for(;;)
			{
				if( (*pIndex >= _XT('A') && *pIndex <= _XT('Z')) ||
					(*pIndex >= _XT('a') && *pIndex <= _XT('z')) ||
					(*pIndex >= _XT('0') && *pIndex <= _XT('9')))
				{

					if(bStarted == vFalse)
					{
						bStarted = vTrue;
						*pBegin = pIndex;
					}
				}
				else
				{
					if(bStarted)
					{
						break;
					}
					if(*pIndex == _XT('>') ||
					  (*pIndex == 0))
					{
						pIndex++;
						curLen++;
						*len = curLen;
						return vFalse;
					}
				}
				pIndex++;
				curLen ++;
			}
			*len = curLen;
			if(bStarted == vTrue)
			{
				*pEnd = pIndex;
				return vTrue;
			}
			return vFalse;
		}

		TBool xXMLTinyParser::findElementValue( TChar** pBegin,TChar** pEnd,TInt* len ,TInt left)
		{
			TChar* pCur = *pBegin;
			TChar* pIndex = pCur;
			TInt   curLen = 0;
			TBool  bStarted = vFalse;
			for(;;)
			{
				if((*pIndex != vNull) &&
					(*pIndex != _XT('<')) &&
					(*pIndex != _XT('>')) &&
					(*pIndex != 0xd) &&
					(*pIndex != 0xa) &&
					(*pIndex != 0x9))
				{

					if(bStarted == vFalse)
					{
						bStarted = vTrue;
						*pBegin = pIndex;
					}
				}
				else
				{
					if(bStarted)
					{
						break;
					}
					if(*pIndex == _XT('<') ||
						(*pIndex == 0))
					{
						*len = curLen;
						return vFalse;
					}
				}
				pIndex++;
				curLen ++;
			}
			*len = curLen;
			if(bStarted == vTrue)
			{
				*pEnd = pIndex;
				return vTrue;
			}
			return vFalse;
		}

		TBool xXMLTinyParser::findAttributeValue( TChar** pBegin,TChar** pEnd,TInt* len ,TInt left)
		{
			TChar* pCur = *pBegin;
			TChar* pIndex = pCur;
			TInt   curLen = 0;
			TBool  bStarted = vFalse;
			for(;;)
			{
				if( (*pIndex >= _XT('A') && *pIndex <= _XT('Z')) ||
					(*pIndex >= _XT('a') && *pIndex <= _XT('z')) ||
					(*pIndex >= _XT('0') && *pIndex <= _XT('9')))
				{

					if(bStarted == vFalse)
					{
						bStarted = vTrue;
						*pBegin = pIndex;
					}
				}
				else
				{
					if(bStarted)
					{
						break;
					}
				}
				pIndex++;
				curLen ++;
			}
			*len = curLen;
			if(bStarted == vTrue)
			{
				*pEnd = pIndex;
				return vTrue;
			}
			return vFalse;
		}

		TBool xXMLTinyParser::findElementFinish( TChar** pBegin,TChar** pEnd,TInt* len ,TInt left)
		{
			TChar* pCur = *pBegin;
			TChar* pIndex = pCur;
			TInt   curLen = 0;
			TBool  bStarted = vFalse;
			for(;;)
			{
				if(*pIndex == _XT('>'))
				{
					curLen++;
					pIndex++;
					*len = curLen;
					*pEnd = pIndex;
					return vTrue;
				}
				curLen++;
				pIndex++;
			}
			return vFalse;
		}
	}
}
